/* ******************************************************************************************************
Filename:	Build_Struct_v61.c:

Purpose:	Read the STI generated PRN and VDF files and construct a MATLAB mat file consisting of a
			nested Project structure.

Author:		Christopher McLeod
			Mantech International Corporation
			Mail Code 540.5
			NASA / Goddard Space Flight Center
			Greenbelt, MD 20771

Created:	2002-10-04

Change Log
Modified:	2003-08-14: Changed the Time History from double precision to single precision. This reduces
            the disk space and memory used by a factor of two. With a maximum of 1.5GB of RAM available
            to MATLAB, the largest VDF size that can be converted is approximately 660MB.
*********************************************************************************************************
Example:
 
>> cd 'D:\Documents\Projects\MATLAB Application Development\Post-test Analysis\Build Data Structure\Ver_06'
>> mex Build_Struct_v61.c
>> Project = Build_Struct_v61('XRAND14');

VDF Header Contents:
Header Record #1:
Sample Rate .......................    8192.00
Number of Channels ................        112
Data Format Flag ..................          0
Data Type Flag ....................          2
Points Per Channel ................  245760.00
Points ............................     245760
Header Record #2:
Title ............................. SWIFT BAT Flight Structure Vib. Test w/d:3303 02JUL02      
Comment ........................... Run-14 X-Axis Random 4.31grms (-6db)                       
Header Record #3:
File Creation Date ................  2-JUL-02  
File Creation Time ................ 09:54:28 2-


From the PRN File:
Number of Channels ................ 112
Test Label ........................ SWIFT BAT Flight Structure Vib. Test w/d:3303 02JUL02      
Module ............................ 1
Test Date ......................... 2-JUL-02
Run Description ................... Run-14 X-Axis Random 4.31grms (-6db)
Low Pass Filter ................... 2000
Setup File ........................ XRAND14
ADF File .......................... XRAND14.vdf

Filename                                     First Point    Last Point    Total Points   Duration(Sec.)
XRAND14.vdf                                   1              245760         245760         30.000000

Channels:
  1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20, 
 21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40, 
 41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60, 
 61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80, 
 81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99, 100, 
101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112
>>
********************************************************************************************************* */
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include "mex.h"

#pragma pack(2)

#define MAX_PER_RECORD 32
#define MAX_CHANNELS 192
#define NUM_CHAN_FIELDS	(sizeof(Chan_field_names)/sizeof(*Chan_field_names))
#define NUM_CHAN_STRUCTS (sizeof(Project.Test_Item.Run.Channel)/sizeof(struct C_Struct))
#define PRN_FRAME_SIZE 43

/* ******************************************************************** */
/*       Declaration of global variables and types                      */
/* ******************************************************************** */
struct C_Struct {
	int		Module;
	int		ChanNbr;
	char	Trans_Loc[31];
	char	Coordinate[7];
	char	Direction[2];
	char	Orientation[2];
	double	Sensitivity;
	char	EU[6];
	char	Trans_Type[7];
	char	Cable_Ext[12];
	char	Serial_Num[17];
	char	Bypass[8];
	char	Coupling[9];
	double	Max_Volts;
	double	Max_EU;
	float	*Time_His;
};

struct R_Struct {
	char			Test_Date[11];
	char			Test_Type[12];
	char			Test_Level[15];
	char			Axis[3];
	double			*Time_Ref;
	int				Num_Chan;
	double			Sample_Rate;
	int				Low_Pass;
	char			Setup_File[20];
	char			ADF_File[23];
	struct	C_Struct	Channel[192];
			char		Descrip[60];
};

struct T_Struct {
	char			Name[60];
	int				WD;
	struct R_Struct	Run;
};

struct P_Struct {
	char			Name[60];
	struct T_Struct	Test_Item;
} Project = {0};

const int RECORD_SIZE    = 128;	/* 128 bytes */

/* * * * * * * * * *    Declare GLOBAL type definitions    * * * * * * * * * * * */
typedef double	Cal_Record[MAX_PER_RECORD];		/* 128 byte block of floating point numbers */
typedef double	Gain_Record[MAX_PER_RECORD];	/* 128 byte block of floating point numbers */

/* * * * * * * * * * * *  Declare GLOBAL variables   * * * * * * * * * * * * * * * * * * * * */
struct VAMP_Header_Rec1 {					/* <<< 128 Byte Header Record >>> */
	unsigned short int	FileType;			/* Word # 01		*/
	unsigned int		SampleRate;			/* Word # 02 & 03	*/
	unsigned int		SpectraMinFreq;		/* Word # 04 & 05	*/
	unsigned short int	NumOfChannels;		/* Word # 06		*/
	unsigned short int	RegionSize;			/* Word # 07		*/
	unsigned short int	DataFormatFlag;		/* Word # 08		*/
	unsigned short int	DataTypeFlag;		/* Word # 09		*/
	unsigned short int	DataSkewFlag;		/* Word # 10		*/
	unsigned int		PointsPerChan;		/* Word # 11 & 12	*/
	unsigned short int	CalsFlag;			/* Word # 13		*/
	unsigned short int	DataFileRevLevel;	/* Word # 14		*/
	int					MuxFactor;			/* Word # 15 & 16	*/
	unsigned short int	ADC_SysID;			/* Word # 17		*/
	unsigned short int	STI_Reserved01;		/* Word # 18		*/
	unsigned short int	STI_Reserved02;		/* Word # 19		*/
	int					Points;				/* Word # 20 & 21	*/
	unsigned short int	PtrToDescrip;		/* Word # 22		*/
	unsigned short int	PtrToCals;			/* Word # 23		*/
	unsigned short int	PtrToADC_Gains;		/* Word # 24		*/
	unsigned short int	PtrToOffset;		/* Word # 25		*/
	unsigned short int	PtrToADC_Fc;		/* Word # 26		*/
	unsigned short int	PtrToADC_SysMap;	/* Word # 27		*/
	unsigned short int	PtrToDateType;		/* Word # 28		*/
	unsigned short int	PtrToChanMap;		/* Word # 29		*/
	unsigned short int	PtrToFilterGains;	/* Word # 30		*/
	unsigned short int	PtrToAnalogParam;	/* Word # 31		*/
	unsigned short int	PtrToDAC_SFS;		/* Word # 32		*/
	unsigned short int	PtrToDAC_Fc;		/* Word # 33		*/
	unsigned short int	PtrToDAC_SysMap;	/* Word # 34		*/
	unsigned short int	PtrToLastHdrRec;	/* Word # 35		*/
	unsigned short int	NumOfDAC_Chan;		/* Word # 36		*/
	unsigned short int	STI_Reserved03;		/* Word # 37		*/
	unsigned short int	PtrToFilterData;	/* Word # 38		*/
	unsigned short int	PtrToTriggerData;	/* Word # 39		*/
	unsigned short int	PtrToSWIFT_Param;	/* Word # 40		*/
	unsigned short int	SizeOfDescriptor;	/* Word # 41		*/
	unsigned short int	STI_Reserved04;		/* Word # 42		*/
	unsigned short int	STI_Reserved05;		/* Word # 43		*/
	unsigned short int	STI_Reserved06;		/* Word # 44		*/
	unsigned short int	STI_Reserved07;		/* Word # 45		*/
	unsigned short int	STI_Reserved08;		/* Word # 46		*/
	unsigned short int	STI_Reserved09;		/* Word # 47		*/
	unsigned short int	STI_Reserved10;		/* Word # 48		*/
	unsigned short int	STI_Reserved11;		/* Word # 49		*/
	unsigned short int	STI_Reserved12;		/* Word # 50		*/
	unsigned short int	STI_Reserved13;		/* Word # 51		*/
	unsigned short int	PtrToVAMPFile;		/* Word # 52		*/
	unsigned short int	PtrToDataFile;		/* Word # 53		*/
	unsigned short int	PtrToData;			/* Word # 54		*/
	unsigned short int	ExpandFileType;		/* Word # 55		*/
	unsigned short int	PtrToExpandFile;	/* Word # 56		*/
	unsigned short int	SizeOfExpFileReg;	/* Word # 57		*/
	unsigned short int	UserReserved01;		/* Word # 58		*/
	unsigned short int	UserReserved02;		/* Word # 59		*/
	unsigned short int	UserReserved03;		/* Word # 60		*/
	unsigned short int	UserReserved04;		/* Word # 61		*/
	unsigned short int	UserReserved05;		/* Word # 62		*/
	unsigned short int	UserReserved06;		/* Word # 63		*/
	unsigned short int	UserReserved07;		/* Word # 64		*/
} HeaderRec1;

struct VAMP_Header_Rec2 {					/* <<< 128 Byte Header Record >>> */
	char				Title[60];			/* Word # 01 - 30	*/
	char				Comment[60];		/* Word # 31 - 60	*/
	unsigned short int	STI_Reserved01;		/* Word # 61		*/
	unsigned short int	STI_Reserved02;		/* Word # 62		*/
	unsigned short int	STI_Reserved03;		/* Word # 63		*/
	unsigned short int	STI_Reserved04;		/* Word # 64		*/
} HeaderRec2;

struct VAMP_Header_Rec3 {								/* <<< 128 Byte Header Record >>> */
	char				File_Creation_Date[12];	/* Word # 01 - 06	*/
	char				File_Creation_Time[12];	/* Word # 07 - 12	*/
	unsigned short int	STI_Reserved[52];		/* Word # 13 - 64	*/
} HeaderRec3;

Cal_Record		Cals[6];					/* 128 byte block of floating point numbers */
Gain_Record		Gains[6];					/* 128 byte block of floating point numbers */
double			Factor[MAX_CHANNELS]	= { 0.0 };
char			VDF_FileName[60]		= {0};
FILE			*FilePtr;

/* * * * * * * * * * * *  Declare Function Prototypes   * * * * * * * * * */

double Floating_Point_VAX_to_IEEE(unsigned int intValue);

void ReadHeader();

void DisplayHeader();

void ADC_Chan_Descriptors(int Display);

void Read_Cals(int NumRecords, int Last_Chan_Num, int Display);

void Read_Gains(int NumRecords, int Last_Chan_Num, int Display);

void Check_Factors();

void Extract_Channel(int First_Point, int Last_Point, int Chan_Num);

void read_vdf(char inBuff[], int Chan_Num);

void sleep(clock_t wait);

/* *************************************************************************** */
/*              End declaration of global variables                            */
/* *************************************************************************** */

/* *************************************************************************** */
/*         Trim the leading and trailing spaces from theString                 */
/* *************************************************************************** */
void TrimString(char theString[])
{
	int index		= 0;
	int first		= 0;
	int last		= 0;
	int length		= 0;
	int numchars	= 0;
	char tmpstr[60] = {0};

	length = strlen(theString);
	if ((theString[0] == ' ') || (theString[length - 1] == ' '))
	{
		while ((theString[index] == ' ') && (index < (length - 1)))
			index++;
		if (index == (length - 1)) /* The string consists of all spaces */
			theString[1] = '\0';
		else
		{
			first = index;
			index = length - 1;
			while (theString[index] == ' ')
				index--;
			last = index;
			numchars = (last - first + 1);
			strncpy(tmpstr, &theString[first], numchars);
			for (index = 0; index < length; index++)
				theString[index] = '\0';
			strncpy(theString, tmpstr, numchars);
		}
	} /* if ((theString[0] != ' ') && (theString[length - 1] != ' ')) */
	return;
}

/* ********************************************************************* */
/* Convert 32 bit VAX floating-point numbers to IEEE (Microsoft Windows) */
/* readable floating-point numbers.                                      */
/* ********************************************************************* */
double Floating_Point_VAX_to_IEEE(unsigned int intValue)
{
	/* Declare local constants */
	const int ExpMask  = 0X00007f80;
	const int SignMask = 0X00008000;
	const int FracMask = 0X00400000;
	const int OneMask  = 0X00000001;

	/* Declare local variables */
	int Exponent	= 0X00000000;
	unsigned int Fraction	= 0X00000000;
	unsigned int fracValue	= 0X00000000;
	unsigned int SignBit	= 0X00000000;
	double CumFracValue = 0.0;
	double BitValue;
	double FinalValue;
	int index;

	/* Calculate the exponent */
	Exponent = intValue & ExpMask;
	Exponent >>= 7;
	Exponent -= 129;

	/* Calculate the fraction component */
	Fraction = _rotl(intValue, 16);

	CumFracValue = 0.0;
	for (index = -23; index <= -1; index++)
	{
		fracValue = Fraction & OneMask;
		BitValue = ldexp((double)(fracValue), index);
		CumFracValue += BitValue;
		Fraction >>= 1;
	}
	CumFracValue += 1.0;
	FinalValue = ldexp(CumFracValue, Exponent);

	/* Apply sign bit */
	SignBit = intValue & SignMask;
	SignBit >>= 15;
	if (SignBit == 1)
		FinalValue *= -1.0;

	return FinalValue;
} /* Floating_Point_VAX_to_IEEE(unsigned int intValue) */


/* ****************************************************************************
 *              Pauses for a specified number of milliseconds.                *
 ****************************************************************************** */
void sleep(clock_t wait)
{
	clock_t goal;
	goal = wait + clock();
	while (goal > clock())
	;
}

/* ****************************************************************************
 * Computational function: read_prn()                                         *
 * Read the STI generated PRN file and create a populated C-style Project     *
 * structure. The C-style structure will be provided as input to the gateway  *
 * function, mexFunction.                                                     *
 ****************************************************************************** */
void read_prn(char inBuff[])
{
	char	inFileName[60]		= {0};
	char	line[130]			= {0};
	char	sModule[3]			= {0};
	char	sChannels[4]		= {0};
	char	sLow_Pass[6]		= {0};
	char	sChanNbr[4]			= {0};
	char	sSensitivity[12]	= {0};
	char	sMaxVolts[7]		= {0};
	char	sMaxEU[12]			= {0};
	char	BlankStr[]			= "     ";
	char	Burst[]				= "Sine Burst";
	char	Random[]			= "Random";
	char	Sweep[]				= "Sine Sweep";
	int		LineCount			= 0;
	int		LinePosition		= 1;
	int		ChanIndex			= -1;
	int		Pass				= 1;
	int		ModuleNum			= 1;
	int		len					= 0;
	double	Points;
	double	Time_Inc;
	int		TR_Index			= 0;
	double	index;

	/* Input file stream */
	FILE	*data_file;

	mexPrintf("\nFrom the PRN File:\n");
	strcpy(inFileName, inBuff);
	strcat(inFileName, ".prn");
	if (( data_file = fopen(inFileName, "r")) == NULL)
	{
		mexPrintf("Could not open input file. \n");
		/* exit (8); */
	}
	else
	{
		/* mexPrintf("File opened for reading\n"); */

		/* Get the total number of channels in the file */
		fgets(line,sizeof(line), data_file);
		fgets(line,sizeof(line), data_file);
		strncpy(sChannels, line+113, 3);
		Project.Test_Item.Run.Num_Chan = atoi(sChannels);
		mexPrintf("Number of Channels ................ %i\n", Project.Test_Item.Run.Num_Chan);
		Project.Test_Item.Run.Num_Chan = HeaderRec1.NumOfChannels;

		/* Reset to the beginning of the file */
		fseek(data_file, 0L, SEEK_SET);

		while (ChanIndex < Project.Test_Item.Run.Num_Chan - 1)
		{
			LineCount++;
			if (fgets(line, sizeof(line), data_file) == NULL)
				mexPrintf("Could not read line.\n");
			else
			{
				LinePosition = LineCount % PRN_FRAME_SIZE;
				if (Pass == 1)
				{
					switch(LinePosition)
					{
					case 1:
						strncpy(Project.Name, line, 59);
						mexPrintf("Test Label ........................ %s\n", Project.Name);
						{ /* Block to extract the Work Directive:
							 Note that this is a temporary solution and does not handle
							 the case where the four digit Work Directive is not the
							 last four digit sequence. */
							int i = 70;
							int found = 0;
							char sWD[5] = {0};

							while ((!found) && (i > 4))
							{
								if (isdigit(line[i]) && isdigit(line[i-1]) && isdigit(line[i-2]) && isdigit(line[i-3]) && !isdigit(line[i-4]))
								{
									found = 1;
									strncpy(sWD, line+(i-3), 4);
									Project.Test_Item.WD = atoi(sWD);
									mexPrintf("Work Directive .................... %i\n", Project.Test_Item.WD);
								}
								i--;
							} /* while (!found) */
						} /* End of WD extraction block */

						strncpy(sModule, line+114, 2);
						Project.Test_Item.Run.Channel[0].Module = atoi(sModule);
						mexPrintf("Module ............................ %i\n", Project.Test_Item.Run.Channel[0].Module);
						strncpy(Project.Test_Item.Run.Test_Date, HeaderRec3.File_Creation_Date,9);
						TrimString(Project.Test_Item.Run.Test_Date);
						mexPrintf("Test Date ......................... %s\n", Project.Test_Item.Run.Test_Date);
						/* ************************************************************* */
						/*          Allocate memory for the Time_Ref buffer              */
						/* ************************************************************* */
						if ((Project.Test_Item.Run.Time_Ref = (double *) malloc(HeaderRec1.Points * sizeof(double))) == NULL)
							mexPrintf("Memory allocation for Project.Test_Item.Run.Time_Ref FAILED!\n");
						else
						{
							/* mexPrintf("Memory allocation for Project.Test_Item.Run.Time_Ref Complete.\n"); */
							Time_Inc = 1.0 / Floating_Point_VAX_to_IEEE(HeaderRec1.SampleRate);
							Points = (double) HeaderRec1.Points;
							TR_Index = 0;
							for (index = 0.0; index < Points; index++)
							{
								*(Project.Test_Item.Run.Time_Ref + TR_Index) = Time_Inc * index;
								TR_Index++;
							}

						}

						strncpy(Project.Test_Item.Run.Test_Level, BlankStr, 2);
						Project.Test_Item.Run.Sample_Rate = Floating_Point_VAX_to_IEEE(HeaderRec1.SampleRate);
						break;
					case 3:
						strncpy(Project.Test_Item.Run.Descrip, line, 59);
						TrimString(Project.Test_Item.Run.Descrip);
						mexPrintf("Run Description ................... %s\n", Project.Test_Item.Run.Descrip);
						break;
					case 4:
						strncpy(sLow_Pass, line+111, 5);
						Project.Test_Item.Run.Low_Pass = atoi(sLow_Pass);
						mexPrintf("Low Pass Filter ................... %i\n", Project.Test_Item.Run.Low_Pass);
						break;
					case 5:
						strncpy(Project.Test_Item.Run.Setup_File, line+35, ((strlen(line) - 35) - 1));
						TrimString(Project.Test_Item.Run.Setup_File);
						mexPrintf("Setup File ........................ %s\n", Project.Test_Item.Run.Setup_File);

						switch(Project.Test_Item.Run.Setup_File[1])
						{
							case 'B':
							case 'b': strcpy(Project.Test_Item.Run.Test_Type, Burst); break;
							case 'R':
							case 'r': strcpy(Project.Test_Item.Run.Test_Type, Random); break;
							case 'S':
							case 's': strcpy(Project.Test_Item.Run.Test_Type, Sweep); break;
							default: mexPrintf("Unknown Test Type.\n"); break;
						}

						switch(Project.Test_Item.Run.Setup_File[0])
						{
							case 'X':
							case 'x':
							case 'Y':
							case 'y':
							case 'Z':
							case 'z':
								strncpy(Project.Test_Item.Run.Axis, Project.Test_Item.Run.Setup_File, 1);
								break;
							default:
								strncpy(Project.Test_Item.Run.Axis, BlankStr, 2);
						}
						break;
					case 6:
						strncpy(Project.Test_Item.Run.ADF_File, line+35, 21);
						TrimString(Project.Test_Item.Run.ADF_File);
						mexPrintf("ADF File .......................... %s\n", Project.Test_Item.Run.ADF_File);
						Pass++;
						break;
					default:
						/* mexPrintf("Unused Line\n"); */ ;
					} /* end of switch(LinePosition) */
				}
				else
				{
					switch(LinePosition)
					{
					case 1:
						strncpy(sModule, line+114, 2);
						ModuleNum = atoi(sModule);
						break;
					case 11:
					case 12:
					case 13:
					case 14:
					case 15:
					case 16:
					case 17:
					case 18:
					case 19:
					case 20:
					case 21:
					case 22:
					case 23:
					case 24:
					case 25:
					case 26:
					case 27:
					case 28:
					case 29:
					case 30:
					case 31:
					case 32:
					case 33:
					case 34:
					case 35:
					case 36:
					case 37:
					case 38:
					case 39:
					case 40:
					case 41:
					case 42:
						ChanIndex++;
						Project.Test_Item.Run.Channel[ChanIndex].Module = ModuleNum;
						strncpy(sChanNbr, line+1, 3);
						Project.Test_Item.Run.Channel[ChanIndex].ChanNbr = atoi(sChanNbr);
						strncpy(Project.Test_Item.Run.Channel[ChanIndex].Trans_Loc, line+5, 30);
						TrimString(Project.Test_Item.Run.Channel[ChanIndex].Trans_Loc);
						strncpy(Project.Test_Item.Run.Channel[ChanIndex].Coordinate, line+35, 6);
						TrimString(Project.Test_Item.Run.Channel[ChanIndex].Coordinate);
						len = strlen(Project.Test_Item.Run.Channel[ChanIndex].Coordinate);
						if ((Project.Test_Item.Run.Channel[ChanIndex].Coordinate[len - 1] == '+') ||
							(Project.Test_Item.Run.Channel[ChanIndex].Coordinate[len - 1] == '-'))
						{
							Project.Test_Item.Run.Channel[ChanIndex].Orientation[0] = Project.Test_Item.Run.Channel[ChanIndex].Coordinate[len - 1];
							Project.Test_Item.Run.Channel[ChanIndex].Orientation[1] = '\0';
							Project.Test_Item.Run.Channel[ChanIndex].Coordinate[len - 1] = '\0';
						}
						len = strlen(Project.Test_Item.Run.Channel[ChanIndex].Coordinate);

						switch(Project.Test_Item.Run.Channel[ChanIndex].Coordinate[len - 1])
						{
							case 'X':
							case 'x':
							case 'Y':
							case 'y':
							case 'Z':
							case 'z':
							case 'R':
							case 'r':
							case 'T':
							case 't':
							{
								Project.Test_Item.Run.Channel[ChanIndex].Direction[0] = Project.Test_Item.Run.Channel[ChanIndex].Coordinate[len - 1];
								Project.Test_Item.Run.Channel[ChanIndex].Direction[1] = '\0';
								Project.Test_Item.Run.Channel[ChanIndex].Coordinate[len - 1] = '\0';
							}
						}

						strncpy(sSensitivity, line+41, 11);
						Project.Test_Item.Run.Channel[ChanIndex].Sensitivity = atof(sSensitivity);
						strncpy(Project.Test_Item.Run.Channel[ChanIndex].EU, line+52, 5);
						TrimString(Project.Test_Item.Run.Channel[ChanIndex].EU);
						strncpy(Project.Test_Item.Run.Channel[ChanIndex].Trans_Type, line+57, 6);
						TrimString(Project.Test_Item.Run.Channel[ChanIndex].Trans_Type);
						strncpy(Project.Test_Item.Run.Channel[ChanIndex].Cable_Ext, line+63, 11);
						TrimString(Project.Test_Item.Run.Channel[ChanIndex].Cable_Ext);
						strncpy(Project.Test_Item.Run.Channel[ChanIndex].Serial_Num, line+74, 16);
						TrimString(Project.Test_Item.Run.Channel[ChanIndex].Serial_Num);
						strncpy(Project.Test_Item.Run.Channel[ChanIndex].Bypass, line+95, 7);
						TrimString(Project.Test_Item.Run.Channel[ChanIndex].Bypass);
						strncpy(Project.Test_Item.Run.Channel[ChanIndex].Coupling, line+102, 8);
						TrimString(Project.Test_Item.Run.Channel[ChanIndex].Coupling);
						strncpy(sMaxVolts, line+110, 6);
						Project.Test_Item.Run.Channel[ChanIndex].Max_Volts = atof(sMaxVolts);
						strncpy(sMaxEU, line+116, (strlen(line) - 116));
						Project.Test_Item.Run.Channel[ChanIndex].Max_EU = atof(sMaxEU);
/*
						mexPrintf("Module No. .......... %i\n", Project.Test_Item.Run.Channel[ChanIndex].Module);
						mexPrintf("Chan No. ............ %i\n", Project.Test_Item.Run.Channel[ChanIndex].ChanNbr);
						mexPrintf("Transducer Location . %s\n", Project.Test_Item.Run.Channel[ChanIndex].Trans_Loc);
						mexPrintf("Coordinateinate ..... %s\n", Project.Test_Item.Run.Channel[ChanIndex].Coordinate);
						mexPrintf("Direction ........... %s\n", Project.Test_Item.Run.Channel[ChanIndex].Direction);
						mexPrintf("Orientation ......... %s\n", Project.Test_Item.Run.Channel[ChanIndex].Orientation);
						mexPrintf("Sensitivity ......... %f\n", Project.Test_Item.Run.Channel[ChanIndex].Sensitivity);
						mexPrintf("EU .................. %s\n", Project.Test_Item.Run.Channel[ChanIndex].EU);
						mexPrintf("Trans_Type .......... %s\n", Project.Test_Item.Run.Channel[ChanIndex].Trans_Type);
						mexPrintf("Cable Ext ........... %s\n", Project.Test_Item.Run.Channel[ChanIndex].Cable_Ext);
						mexPrintf("Serial No. .......... %s\n", Project.Test_Item.Run.Channel[ChanIndex].Serial_Num);
						mexPrintf("Bypass .............. %s\n", Project.Test_Item.Run.Channel[ChanIndex].Bypass);
						mexPrintf("Coupling ............ %s\n", Project.Test_Item.Run.Channel[ChanIndex].Coupling);
						mexPrintf("Max_Volts ........... %f\n", Project.Test_Item.Run.Channel[ChanIndex].Max_Volts);
						mexPrintf("Max_EU .............. %f\n", Project.Test_Item.Run.Channel[ChanIndex].Max_EU);
*/
						break;
					default:
						/* mexPrintf("Unused Line\n"); */ ;
					} /* end of switch(LinePosition) */
					Pass++;
				} /* end of if-else (Pass == 1) */
/*
				mexPrintf(" -----------------------------------------------------------\n\n");
*/
			} /* end of if-else (fgets(line, sizeof(line), data_file) == NULL) */
		} /* while (ChanIndex <= Project.Test_Item.Run.Num_Chan) */
		fclose(data_file);
	} /* end of else */
/*
	mexPrintf("\n\n");
*/
}

/* ***************************************************************************** */
/* ***************************************************************************** */
void ReadHeader()
{
	const int COUNT = 1;
	int rec1_count;
	int rec2_count;
	int rec3_count;

	/* Open for read (will fail if file "data" does not exist) */
   if( (FilePtr  = fopen( VDF_FileName, "r+b" )) == NULL )
		mexPrintf("The file %s was not opened.\n", VDF_FileName);
   else
	{
		/* mexPrintf("The file %s has been opened.\n\n", VDF_FileName); */
		fseek(FilePtr, 0L, SEEK_SET);
		rec1_count = fread(&HeaderRec1, sizeof(struct VAMP_Header_Rec1), COUNT, FilePtr);
		rec2_count = fread(&HeaderRec2, sizeof(struct VAMP_Header_Rec2), COUNT, FilePtr);
		rec3_count = fread(&HeaderRec3, sizeof(struct VAMP_Header_Rec3), COUNT, FilePtr);

		/* Close stream */
		if( fclose( FilePtr ) )
			mexPrintf("The file %s was not closed.\n", VDF_FileName);

		HeaderRec2.Title[59] = '\0';
		HeaderRec2.Comment[59] = '\0';

		HeaderRec3.File_Creation_Date[11] = '\0';
		HeaderRec3.File_Creation_Time[11] = '\0';

	}
} /* ReadHeader() */

/* ***************************************************************************** */
/* ***************************************************************************** */
void DisplayHeader()
{
	/* int i; */
	mexPrintf("\nVDF Header Contents:\n");
	mexPrintf("Header Record #1:\n");
/*	mexPrintf("FileType .......................... %10u\n", HeaderRec1.FileType); */
	mexPrintf("Sample Rate ....................... %10.2f\n", Floating_Point_VAX_to_IEEE(HeaderRec1.SampleRate));
/*	mexPrintf("Spectra Min Freq .................. %10.2f\n", Floating_Point_VAX_to_IEEE(HeaderRec1.SpectraMinFreq)); */
	mexPrintf("Number of Channels ................ %10u\n", HeaderRec1.NumOfChannels);
/*
	mexPrintf("Region Size ....................... %10u\n", HeaderRec1.RegionSize);
*/
	mexPrintf("Data Format Flag .................. %10u\n", HeaderRec1.DataFormatFlag);
	mexPrintf("Data Type Flag .................... %10u\n", HeaderRec1.DataTypeFlag);
/*
	mexPrintf("Data Skew Flag .................... %10u\n", HeaderRec1.DataSkewFlag);
*/
	mexPrintf("Points Per Channel ................ %10.2f\n", Floating_Point_VAX_to_IEEE(HeaderRec1.PointsPerChan));

/*	mexPrintf("Cals Flag ......................... %10u\n", HeaderRec1.CalsFlag);
	mexPrintf("Data File Rev Level ............... %10u\n", HeaderRec1.DataFileRevLevel);
	mexPrintf("Mux Factor ........................ %10i\n", HeaderRec1.MuxFactor);
	mexPrintf("ADC Sys ID ........................ %10u\n", HeaderRec1.ADC_SysID);
*/
	mexPrintf("Points ............................ %10u\n", HeaderRec1.Points);
/*
	mexPrintf("Ptr to Descriptors ................ %10u\n", HeaderRec1.PtrToDescrip);
	mexPrintf("Ptr to Cals....... ................ %10u\n", HeaderRec1.PtrToCals);
	mexPrintf("Ptr to ADC Gains .................. %10u\n", HeaderRec1.PtrToADC_Gains);
	mexPrintf("Ptr to Offset ..................... %10u\n", HeaderRec1.PtrToOffset);
	mexPrintf("Ptr to ADC Fc Table ............... %10u\n", HeaderRec1.PtrToADC_Fc);
	mexPrintf("Ptr to ADC Sys Map ................ %10u\n", HeaderRec1.PtrToADC_SysMap);
	mexPrintf("Ptr to Data Type .................. %10u\n", HeaderRec1.PtrToDateType);
	mexPrintf("Ptr to Channel Map ................ %10u\n", HeaderRec1.PtrToChanMap);
	mexPrintf("Ptr to Filter Gains ............... %10u\n", HeaderRec1.PtrToFilterGains);
	mexPrintf("Ptr to Analog System Params ....... %10u\n", HeaderRec1.PtrToAnalogParam);
	mexPrintf("Ptr to DAC SFS .................... %10u\n", HeaderRec1.PtrToDAC_SFS);
	mexPrintf("Ptr to DAC Fc Table ............... %10u\n", HeaderRec1.PtrToDAC_Fc);
	mexPrintf("Ptr to DAC Sys Map ................ %10u\n", HeaderRec1.PtrToDAC_SysMap);
	mexPrintf("Ptr to Last Header Record ......... %10u\n", HeaderRec1.PtrToLastHdrRec);
	mexPrintf("Ptr to Number of DAC Channels ..... %10u\n", HeaderRec1.NumOfDAC_Chan);
	mexPrintf("Ptr to Filter Data ................ %10u\n", HeaderRec1.PtrToFilterData);
	mexPrintf("Ptr to Trigger Data ............... %10u\n", HeaderRec1.PtrToTriggerData);
	mexPrintf("Ptr to SWIFT Param ................ %10u\n", HeaderRec1.PtrToSWIFT_Param);
	mexPrintf("Size of Descriptor ................ %10u\n", HeaderRec1.SizeOfDescriptor);
	mexPrintf("Ptr to VAMP Filename .............. %10u\n", HeaderRec1.PtrToVAMPFile);
	mexPrintf("Ptr to Data Filename .............. %10u\n", HeaderRec1.PtrToDataFile);
	mexPrintf("Ptr to Data ....................... %10u\n", HeaderRec1.PtrToData);
	mexPrintf("Expanded File Type ................ %10u\n", HeaderRec1.ExpandFileType);
	mexPrintf("Ptr to Expanded File Type ......... %10u\n", HeaderRec1.PtrToExpandFile);
	mexPrintf("Size of Expanded File Reg ......... %10u\n\n", HeaderRec1.SizeOfExpFileReg);
*/
	mexPrintf("Header Record #2:\n");
	mexPrintf("Title ............................. %s\n", HeaderRec2.Title);
	mexPrintf("Comment ........................... %s\n", HeaderRec2.Comment);

	mexPrintf("Header Record #3:\n");
	mexPrintf("File Creation Date ................ %s\n", HeaderRec3.File_Creation_Date);
	mexPrintf("File Creation Time ................ %s\n\n", HeaderRec3.File_Creation_Time);
	

	/* Troubleshooting section */
	/*
	unsigned short int* ptr = &HeaderRec1.FileType;

	for (i = 0; i <= 50; i++)
	{
		mexPrintf("Word: %3i   Location: %8lu  Value: %10u\n", i+1, ptr+i, *(ptr+i));
	}
	mexPrintf("\n");
	*/
	/*
	mexPrintf("Address Locations:\n");
	mexPrintf("Record #1:\n");
	mexPrintf("FileType ................... %lu\n", &HeaderRec1.FileType);
	mexPrintf("Sample Rate ................ %lu\n", &HeaderRec1.SampleRate);
	mexPrintf("Spectra Min Freq ........... %lu\n", &HeaderRec1.SpectraMinFreq);
	mexPrintf("Number of Channels ......... %lu\n", &HeaderRec1.NumOfChannels);
	mexPrintf("Region Size ................ %lu\n", &HeaderRec1.RegionSize);
	mexPrintf("Data Format Flag ........... %lu\n", &HeaderRec1.DataFormatFlag);
	mexPrintf("Data Type Flag ............. %lu\n", &HeaderRec1.DataTypeFlag);
	mexPrintf("Data Skew Flag ............. %lu\n", &HeaderRec1.DataSkewFlag);
	mexPrintf("Size of Descriptor ......... %lu\n", &HeaderRec1.SizeOfDescriptor);
	mexPrintf("Ptr to Data ................ %lu\n\n", &HeaderRec1.PtrToData);
	mexPrintf("Title ...................... %lu\n\n", &HeaderRec2.Title);
	mexPrintf("File Creation Date ......... %lu\n\n", &HeaderRec3.File_Creation_Date);

	mexPrintf("Variable Sizes:\n");
	mexPrintf("Record #1:\n");
	mexPrintf("HeaderRec1 ................. %u\n", sizeof(HeaderRec1));
	mexPrintf("FileType ................... %u\n", sizeof(HeaderRec1.FileType));
	mexPrintf("Sample Rate ................ %u\n", sizeof(HeaderRec1.SampleRate));
	mexPrintf("Spectra Min Freq ........... %u\n", sizeof(HeaderRec1.SpectraMinFreq));
	mexPrintf("Number of Channels ......... %u\n", sizeof(HeaderRec1.NumOfChannels));
	mexPrintf("Region Size ................ %u\n", sizeof(HeaderRec1.RegionSize));
	mexPrintf("Data Format Flag ........... %u\n", sizeof(HeaderRec1.DataFormatFlag));
	mexPrintf("Data Type Flag ............. %u\n", sizeof(HeaderRec1.DataTypeFlag));
	mexPrintf("Data Skew Flag ............. %u\n", sizeof(HeaderRec1.DataSkewFlag));
	mexPrintf("Ptr to Data ................ %u\n\n", sizeof(HeaderRec1.PtrToData));
	mexPrintf("HeaderRec2 ................. %u\n", sizeof(HeaderRec2));
	mexPrintf("HeaderRec3 ................. %u\n", sizeof(HeaderRec2));
	*/

} /* DisplayHeader() */

/* ***************************************************************************** */
/* ***************************************************************************** */
void ADC_Chan_Descriptors(int Display)
{
	const int Descriptors_Per_Record = 4;	/* (128 byte record) / (32 byte string) = 4 descriptor per rec */
	typedef char String32[32];
	typedef String32 ADC_Chan_Descriptor_Rec[4];

	ADC_Chan_Descriptor_Rec	Description;
	String32				Descrip_Array[MAX_CHANNELS];
	int						ADC_Rec_Index;
	int						Chan_Index;
	int						Index_Offset = 0;
	int						Last_Rec;
	int						Rec_Index;
	long					FilePos;

	/* Open for read (will fail if file "data" does not exist) */
	if( (FilePtr  = fopen( VDF_FileName, "r+b" )) == NULL )
		mexPrintf("The file %s was not opened.\n", VDF_FileName);
	else
	{
		FilePos = (long)((HeaderRec1.PtrToDescrip - 1) * RECORD_SIZE);
		fseek(FilePtr, FilePos, SEEK_SET);

		/* Read all of the channel descriptors */
		Last_Rec = (int)(((HeaderRec1.NumOfChannels - 1) / Descriptors_Per_Record) + 1);
		for (ADC_Rec_Index = 1; ADC_Rec_Index <= Last_Rec; ADC_Rec_Index++)
		{
			fread(&Description, sizeof(ADC_Chan_Descriptor_Rec), 1, FilePtr);
			for (Rec_Index = 0; Rec_Index < Descriptors_Per_Record; Rec_Index++)
			{
				Description[Rec_Index][31] = '\0';
				strcpy(Descrip_Array[Rec_Index + Index_Offset], Description[Rec_Index]);
			}
			Index_Offset += 4;
		}
		if( fclose( FilePtr ) )
			mexPrintf("The file %s was not closed.\n", VDF_FileName);

		/* Display the channel descriptors */
		if (Display == 0)
		{
			mexPrintf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
			mexPrintf("ADC Channel Descriptors:\n");
			mexPrintf("Starting Record Number ............... %u\n", HeaderRec1.PtrToDescrip);
			for (Chan_Index = 0; Chan_Index <= (HeaderRec1.NumOfChannels - 1); Chan_Index++)
				mexPrintf("Channel %3i ... %s\n", Chan_Index+1, Descrip_Array[Chan_Index]);
			mexPrintf("\n");
		}
	} /* else */
} /* ADC_Chan_Descriptors */

/* ***************************************************************************** */
/*                 Sensitivity = 1000.0 / Cals                                   */
/* ***************************************************************************** */
void Read_Cals(int NumRecords, int Last_Chan_Num, int Display)
{
	int				Channel;
	int				Last_Chan;
	int				Last_Rec;
	int				Rec_Num;
	long			FilePos;
	int				intCals[MAX_PER_RECORD] = { 0 };
	int				Chan_Num;
	int				Index;

	/* Open for read (will fail if file "data" does not exist) */
	if( (FilePtr  = fopen( VDF_FileName, "r+b" )) == NULL )
		mexPrintf("The file %s was not opened.\n", VDF_FileName);
	else
	{
		FilePos = (long)((HeaderRec1.PtrToCals - 1) * RECORD_SIZE);
		fseek(FilePtr, FilePos, SEEK_SET);

		/* Read all of the channel descriptors */
		for (Rec_Num = 0; Rec_Num < NumRecords; Rec_Num++)
		{
			fread(&intCals, RECORD_SIZE, 1, FilePtr);
			for (Index = 0; Index < MAX_PER_RECORD; Index++)
			{
				Cals[Rec_Num][Index] = Floating_Point_VAX_to_IEEE(intCals[Index]);
				intCals[Index] = 0;
			}
		}
		if( fclose( FilePtr ) )
			mexPrintf("The file %s was not closed.\n", VDF_FileName);
		Last_Rec = (int)(((HeaderRec1.NumOfChannels - 1) / MAX_PER_RECORD) + 1);
		Last_Chan = (int)(((HeaderRec1.NumOfChannels - 1) % MAX_PER_RECORD) + 1);

		if (Display == 0)
		{
			mexPrintf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n");
			mexPrintf("Channel Calibrations Section:\n");
			mexPrintf("Chan    Calabration\n");
			Channel = 1;
			for (Rec_Num = 0; Rec_Num <= (Last_Rec - 2); Rec_Num++)
			{
				for (Chan_Num = 0; Chan_Num <= (MAX_PER_RECORD - 1); Chan_Num++)
				{
					mexPrintf("%4i    %9.4f  =>  %9.4f\n", Channel, Cals[Rec_Num][Chan_Num], (1 / Cals[Rec_Num][Chan_Num] * 1000.0));
					Channel++;
				}
			}

			Rec_Num = Last_Rec - 1;
			for (Chan_Num = 0; Chan_Num <= (Last_Chan - 1); Chan_Num++)
			{
				mexPrintf("%4i    %9.4f  =>  %9.4f\n", Channel, Cals[Rec_Num][Chan_Num], (1 / Cals[Rec_Num][Chan_Num] * 1000.0));
				Channel++;
			}
		} /* if (Display == 0) */
	}
} /* Read_Cals */

/* ***************************************************************************** */
/*                    Max Volts = 5.0 / Gains                                    */
/* ***************************************************************************** */
void Read_Gains(int NumRecords, int Last_Chan_Num, int Display)
{
	int				Channel;
	int				Last_Chan;
	int				Last_Rec;
	int				Rec_Num;
	long			FilePos;
	int				intGains[MAX_PER_RECORD] = { 0 };
	int				Chan_Num;
	int				Index;

	/* Open for read (will fail if file "data" does not exist) */
   if( (FilePtr  = fopen( VDF_FileName, "r+b" )) == NULL )
		mexPrintf("The file %s was not opened.\n", VDF_FileName);
   else
	{
		FilePos = (long)((HeaderRec1.PtrToADC_Gains - 1) * RECORD_SIZE);
		fseek(FilePtr, FilePos, SEEK_SET);

		/* Read all of the channel descriptors */
		for (Rec_Num = 0; Rec_Num < NumRecords; Rec_Num++)
		{
			fread(&intGains, RECORD_SIZE, 1, FilePtr);
			for (Index = 0; Index < MAX_PER_RECORD; Index++)
			{
				Gains[Rec_Num][Index] = Floating_Point_VAX_to_IEEE(intGains[Index]);
				intGains[Index] = 0;
			}
		}
		if( fclose( FilePtr ) )
			mexPrintf("The file %s was not closed.\n", VDF_FileName);
		Last_Rec = (int)(((HeaderRec1.NumOfChannels - 1) / MAX_PER_RECORD) + 1);
		Last_Chan = (int)(((HeaderRec1.NumOfChannels - 1) % MAX_PER_RECORD) + 1);

		if (Display == 0)
		{
			mexPrintf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n");
			mexPrintf("Channel Gains Section:\n");
			mexPrintf("Chan    Gain\n");
			Channel = 1;
			for (Rec_Num = 0; Rec_Num <= (Last_Rec - 2); Rec_Num++)
			{
				for (Chan_Num = 0; Chan_Num <= (MAX_PER_RECORD - 1); Chan_Num++)
				{
					mexPrintf("%4i    %9.4f  =>  %9.4f\n", Channel, Gains[Rec_Num][Chan_Num], (5.0 / Gains[Rec_Num][Chan_Num]));
					Channel++;
				}
			}

			Rec_Num = Last_Rec - 1;
			for (Chan_Num = 0; Chan_Num <= (Last_Chan - 1); Chan_Num++)
			{
				mexPrintf("%4i    %9.4f  =>  %9.4f\n", Channel, Gains[Rec_Num][Chan_Num], (5.0 / Gains[Rec_Num][Chan_Num]));
				Channel++;
			}
		} /* if (Display == 0) */
	}
} /* Read_Gains */

/* ***************************************************************************** */
/* ***************************************************************************** */
void Check_Factors()
{
	int			NumRecords;
	int			Last_Chan_Num;
	int			Index;
	int			Display = 1;
	int			Rec_Num;
	int			Rec_Index;

	NumRecords = (int)(((HeaderRec1.NumOfChannels - 1) / MAX_PER_RECORD) + 1);
	Last_Chan_Num = (int)(((HeaderRec1.NumOfChannels - 1) % MAX_PER_RECORD) + 1);

	Display = 1;
	if (HeaderRec1.PtrToCals >= 0)
		Read_Cals(NumRecords, Last_Chan_Num, Display);

	Display = 1;
	if (HeaderRec1.PtrToADC_Gains >= 0)
		Read_Gains(NumRecords, Last_Chan_Num, Display);

	switch(HeaderRec1.DataTypeFlag)
	{
		case 0 : mexPrintf("\n"); break; /* Do nothing. Already in Engineering Units */
		case 1 : /* Data values in volts */
			{
				Index = 0;
				for (Rec_Num = 0; Rec_Num < NumRecords; Rec_Num++)
					for (Rec_Index = 0; Rec_Index < MAX_PER_RECORD; Rec_Index++)
					{
						Factor[Index] = Cals[Rec_Num][Rec_Index] / Gains[Rec_Num][Rec_Index];
						Index++;
					}
			}
			break;
		case 2: /* Data values in ADC counts */
			{
				Index = 0;
				for (Rec_Num = 0; Rec_Num < (NumRecords - 1); Rec_Num++)
					for (Rec_Index = 0; Rec_Index < MAX_PER_RECORD; Rec_Index++)
					{
						Factor[Index] = Cals[Rec_Num][Rec_Index] / Gains[Rec_Num][Rec_Index];
						Index++;
					}
				Rec_Num = NumRecords - 1;
				for (Rec_Index = 0; Rec_Index < Last_Chan_Num; Rec_Index++)
				{
					Factor[Index] = Cals[Rec_Num][Rec_Index] / Gains[Rec_Num][Rec_Index];
					Index++;
				}
				for (Index = 0; Index < HeaderRec1.NumOfChannels; Index++)
					Factor[Index] = Factor[Index] * 5.0 / 32767.0;
			}
			break;
		default: mexPrintf("Error in Data Type Frag. Invalid value [%i] read in.\n", HeaderRec1.DataTypeFlag);
	} /* switch(HeaderRec1.DataTypeFlag) */
} /* Check_Factors */

/* ***************************************************************************** */
/* The Data Format Flag indicates whether the data is stored in floating-point   */
/* format with 32 points per record or integer format with 64 points per record. */
/* Extract the time history data for each channel in frames of the appropiate    */
/* size and accumulate the data in a the buffer indicated by Time_His.           */
/* ***************************************************************************** */
void Extract_Channel(int First_Point, int Last_Point, int Chan_Num)
{
	int					Channel_Spacing;
	signed short int	Data[64];
	int					Display;
	double				Duration;
	long				FilePos;
	int					First_Data_Rec;
	int					First_Rec_Offset;
	int					RecNum;
	int					Samples_Per_Record;
	int					Total_Num_Records;
	int					Total_Points;
	int					Rec_Count;
	int					Consecutive_Records;
	int					Index;
	int					RB_Index = 0;

	Display = 1;
	ADC_Chan_Descriptors(Display);
	if (Chan_Num == 0)
		mexPrintf("\nFilename                                     First Point    Last Point    Total Points   Duration(Sec.)\n");

	Total_Points = Last_Point - First_Point + 1;
	Duration = Total_Points / Floating_Point_VAX_to_IEEE(HeaderRec1.SampleRate);
	if (Chan_Num == 0)
		mexPrintf("%-45s %-11i    %-11i    %-11i    %-f\n\n", VDF_FileName, First_Point, Last_Point, Total_Points, Duration);
	Check_Factors();

/* List channel number as data is extracted
	if ((Chan_Num + 1) == 1)
		mexPrintf("Channels:\n");
	if (((Chan_Num + 1) % 20) == 0)
		mexPrintf("%3i, \n", (Chan_Num + 1));
	else
	{
		if ((HeaderRec1.NumOfChannels - 1) == Chan_Num)
			mexPrintf("%3i", (Chan_Num + 1));
		else
			mexPrintf("%3i, ", (Chan_Num + 1));
	}
*/
	/* Open for read (will fail if file "data" does not exist) */
	if( (FilePtr  = fopen( VDF_FileName, "r+b" )) == NULL )
		mexPrintf("The file %s was not opened.\n", VDF_FileName);
	else
	{
		fseek(FilePtr, 0L, SEEK_SET);

		switch(HeaderRec1.DataFormatFlag)
		{
			case 0 : Samples_Per_Record = 64; break; /* Data stored in integer format. (I.E. 2 bytes/sample) */
			case 1 : Samples_Per_Record = 32; break; /* Data stored in floating-point format. (I.E. 4 bytes/sample) */
			default: mexPrintf("Invalid Data Format Flag value of [%2i] read.\n", HeaderRec1.DataFormatFlag);
		}

		/* ************************************************************* */
		/*          Allocate memory for the Time_His buffer              */
		/* ************************************************************* */
		if ((Project.Test_Item.Run.Channel[Chan_Num].Time_His  = (float *) malloc(HeaderRec1.Points * sizeof(float))) == NULL)
			mexPrintf("Memory allocation for Project.Test_Item.Run.Channel[Chan_Num].Time_His FAILED!\n");
		else
		{
			/* mexPrintf("Memory allocation for Project.Test_Item.Run.Channel[Chan_Num].Time_His Complete.\n"); */
			Channel_Spacing = HeaderRec1.MuxFactor * HeaderRec1.NumOfChannels;
			First_Data_Rec = (int)((First_Point - 1) / Samples_Per_Record);
			First_Rec_Offset = First_Data_Rec * HeaderRec1.NumOfChannels;
			Total_Num_Records = (int)((Last_Point - First_Point + 1) / Samples_Per_Record);

			/* Chan_Num is passed in from mexFunction */
			for (Rec_Count = 0; Rec_Count < Total_Num_Records; Rec_Count++)
			{
				RecNum = (HeaderRec1.PtrToData - 1) + First_Rec_Offset + Chan_Num;
				FilePos = (long)(RecNum * RECORD_SIZE);
				fseek(FilePtr, FilePos, SEEK_SET);

				for (Consecutive_Records = 1; Consecutive_Records <= HeaderRec1.MuxFactor; Consecutive_Records++)
				{
					fread(&Data, RECORD_SIZE, 1, FilePtr);
					/*	Convert DAC counts to Engineering Units and assign to Project.Test_Item.Run.Channel[Chan_Num].Time_His */
					for (Index = 0; Index < Samples_Per_Record; Index++)
					{
						*(Project.Test_Item.Run.Channel[Chan_Num].Time_His + RB_Index) = (float)(Data[Index] * Factor[Chan_Num]);
						RB_Index++;
					}
				} /* for (Consecutive_Records = 1; Consecutive_Records <= HeaderRec1.MuxFactor; Consecutive_Records++) */
				First_Rec_Offset = First_Rec_Offset + Channel_Spacing;
			} /* for (Rec_Count = 0; Rec_Count < Total_Num_Records; Rec_Count++) */
		} /* else Project.Test_Item.Run.Channel[Chan_Num].Time_His */
	} /* else FilePtr */

	if( fclose( FilePtr ) )
		mexPrintf("The file %s was not closed.\n", VDF_FileName);

} /* Extract_Channel */

/* ****************************************************************************
 * Computational function: read_vdf()                                         *
 * Read the STI generated VDF file and populate the C-style Project structure *
 * with the time history data. The C-style structure will be provided as      *
 * input to the gateway function, mexFunction.                                *
 ****************************************************************************** */
void read_vdf(char inBuff[], int Chan_Num)
{
	int First_Point = 1;
	int Last_Point  = 1;

	strcpy(VDF_FileName, inBuff);
	strcat(VDF_FileName, ".vdf");

	if (Chan_Num == -1)
	{
		ReadHeader();
		DisplayHeader();
	}
	if (Chan_Num >= 0)
		Extract_Channel(1, HeaderRec1.Points, Chan_Num);
	return;
}

/* ****************************************************************************
 * Gateway function: mexFunction                                              *
 * Provide an interface between the computational "C" language functions,     *
 * read_prn, read_vdf, and MATLAB.                                            *
 ****************************************************************************** */
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
	const char *Chan_field_names[] = {"Module", "ChanNbr", "Trans_Loc", "Coordinate", "Direction", "Orientation",
									  "Sensitivity", "EU", "Trans_Type", "Cable_Ext", "Serial_Num", "Bypass",
									  "Coupling", "Max_Volts", "Max_EU", "Time_His"};

	const char *Run_field_names[] = {"Test_Date", "Test_Type", "Test_Level", "Axis", "Time_Ref", "Num_Chan",
									 "Sample_Rate", "Low_Pass", "Setup_File", "ADF_File", "Channel", "Descrip"};

	const char *TestItem_field_names[] = {"TI_Name", "WD", "Run"};

	const char *Project_field_names[] = {"Name", "Test_Item"};

	int dims[2] = {1, NUM_CHAN_STRUCTS};

	int Name_field, Test_Item_field;

	int TI_Name_field, WD_field, Run_field;

	int Test_Date_field, Test_Type_field, Test_Level_field, Axis_field, Time_Ref_field, Num_Chan_field,
		Sample_Rate_field, Low_Pass_field, Setup_File_field, ADF_File_field, Channel_field, Descrip_field;

	int Module_field, ChanNbr_field, Trans_Loc_field, Coordinate_field, Direction_field, Orientation_field,
		Sensitivity_field, EU_field, Trans_Type_field, Cable_Ext_field, Serial_Num_field, Bypass_field,
		Coupling_field, Max_Volts_field, Max_EU_field, Time_His_field;

	int index;

	mxArray *ChanStruct;
	mxArray *RunStruct;
	mxArray *TestItemStruct;

	/* Error checking for proper number of input & output arguments */
	/*
	mexPrintf("nrhs .................. %i\n", nrhs);
	mexPrintf("lrhs .................. %i\n", nlhs);
	*/
	/* ******************************************************************** */
	/*       Create a 1-by-n array of structures for the channel data       */
	/* ******************************************************************** */
	ChanStruct = mxCreateStructArray(2, dims, NUM_CHAN_FIELDS, Chan_field_names);

	/* ******************************************************************** */
	/*           Create a 1-by-1 struct matrix for the Run data             */
	/* ******************************************************************** */
	RunStruct = mxCreateStructMatrix(1, 1, 12, Run_field_names);

	/* ******************************************************************** */
	/*       Create a 1-by-1 struct matrix for the Test_Item data           */
	/* ******************************************************************** */
	TestItemStruct = mxCreateStructMatrix(1, 1, 3, TestItem_field_names);

	/* ******************************************************************** */
	/*        Create a 1-by-1 struct matrix for the Project data            */
	/* ******************************************************************** */
	plhs[0] = mxCreateStructMatrix(1, 1, 2, Project_field_names);

	/* ******************************************************************** */
	/*          Get the field numbers for each structure field              */
	/* ******************************************************************** */
	/*                   Project field numbers:                             */
	/* ******************************************************************** */
	Name_field     = mxGetFieldNumber(plhs[0], "Name");
	Test_Item_field = mxGetFieldNumber(plhs[0], "Test_Item");
	/*
	mexPrintf("\nProject field numbers:\n");
	mexPrintf("Name_field ............ %i\n", Name_field);
	mexPrintf("Test_Item_field ........ %i\n", Test_Item_field);
	*/
	/* ******************************************************************** */
	/*                 Test_Item field numbers:                             */
	/* ******************************************************************** */
	TI_Name_field = mxGetFieldNumber(TestItemStruct, "TI_Name");
	WD_field      = mxGetFieldNumber(TestItemStruct, "WD");
	Run_field     = mxGetFieldNumber(TestItemStruct, "Run");
	/*
	mexPrintf("\nTest_Item field numbers:\n");
	mexPrintf("TI_Name_field ......... %i\n", TI_Name_field);
	mexPrintf("WD_field .............. %i\n", WD_field);
	mexPrintf("Run_field ............. %i\n", Run_field);
	*/
	/* ******************************************************************** */
	/*                    Run field numbers:                                */
	/* ******************************************************************** */
	Test_Date_field   = mxGetFieldNumber(RunStruct, "Test_Date");
	Test_Type_field   = mxGetFieldNumber(RunStruct, "Test_Type");
	Test_Level_field  = mxGetFieldNumber(RunStruct, "Test_Level");
	Axis_field        = mxGetFieldNumber(RunStruct, "Axis");
	Time_Ref_field    = mxGetFieldNumber(RunStruct, "Time_Ref");
	Num_Chan_field    = mxGetFieldNumber(RunStruct, "Num_Chan");
	Sample_Rate_field = mxGetFieldNumber(RunStruct, "Sample_Rate");
	Low_Pass_field    = mxGetFieldNumber(RunStruct, "Low_Pass");
	Setup_File_field  = mxGetFieldNumber(RunStruct, "Setup_File");
	ADF_File_field    = mxGetFieldNumber(RunStruct, "ADF_File");
	Channel_field     = mxGetFieldNumber(RunStruct, "Channel");
	Descrip_field     = mxGetFieldNumber(RunStruct, "Descrip");
/*
	mexPrintf("\nRun field numbers:\n");
	mexPrintf("Test_Date_field ....... %i\n", Test_Date_field);
	mexPrintf("Test_Type_field ....... %i\n", Test_Type_field);
	mexPrintf("Test_Level_field ...... %i\n", Test_Level_field);
	mexPrintf("Axis_field ............ %i\n", Axis_field);
	mexPrintf("Time_Ref_field ........ %i\n", Time_Ref_field);
	mexPrintf("Num_Chan_field ........ %i\n", Num_Chan_field);
	mexPrintf("Sample_Rate_field ..... %i\n", Sample_Rate_field);
	mexPrintf("Low_Pass_field ........ %i\n", Low_Pass_field);
	mexPrintf("Setup_File_field ...... %i\n", Setup_File_field);
	mexPrintf("ADF_File_field ........ %i\n", ADF_File_field);
	mexPrintf("Channel_field ......... %i\n", Channel_field);
	mexPrintf("Descrip_field ......... %i\n", Descrip_field);
*/
	/* ******************************************************************** */
	/*                     Chan field numbers:                              */
	/* ******************************************************************** */
	Module_field      = mxGetFieldNumber(ChanStruct, "Module");
	ChanNbr_field     = mxGetFieldNumber(ChanStruct, "ChanNbr");
	Trans_Loc_field   = mxGetFieldNumber(ChanStruct, "Trans_Loc");
	Coordinate_field  = mxGetFieldNumber(ChanStruct, "Coordinate");
	Direction_field   = mxGetFieldNumber(ChanStruct, "Direction");
	Orientation_field = mxGetFieldNumber(ChanStruct, "Orientation");
	Sensitivity_field = mxGetFieldNumber(ChanStruct, "Sensitivity");
	EU_field          = mxGetFieldNumber(ChanStruct, "EU");
	Trans_Type_field  = mxGetFieldNumber(ChanStruct, "Trans_Type");
	Cable_Ext_field   = mxGetFieldNumber(ChanStruct, "Cable_Ext");
	Serial_Num_field  = mxGetFieldNumber(ChanStruct, "Serial_Num");
	Bypass_field      = mxGetFieldNumber(ChanStruct, "Bypass");
	Coupling_field    = mxGetFieldNumber(ChanStruct, "Coupling");
	Max_Volts_field   = mxGetFieldNumber(ChanStruct, "Max_Volts");
	Max_EU_field      = mxGetFieldNumber(ChanStruct, "Max_EU");
	Time_His_field    = mxGetFieldNumber(ChanStruct, "Time_His");
	/*
	mexPrintf("\nChan field numbers:\n");
	mexPrintf("Module_field .......... %i\n", Module_field);
	mexPrintf("ChanNbr_field ......... %i\n", ChanNbr_field);
	mexPrintf("Trans_Loc_field ....... %i\n", Trans_Loc_field);
	mexPrintf("Coordinate_field ...... %i\n", Coordinate_field);
	mexPrintf("Direction_field ....... %i\n", Direction_field);
	mexPrintf("Orientation_field ..... %i\n", Orientation_field);
	mexPrintf("Sensitivity_field ..... %i\n", Sensitivity_field);
	mexPrintf("EU_field .............. %i\n", EU_field);
	mexPrintf("Trans_Type_field ...... %i\n", Trans_Type_field);
	mexPrintf("Cable_Ext_field ....... %i\n", Cable_Ext_field);
	mexPrintf("Serial_Num_field ...... %i\n", Serial_Num_field);
	mexPrintf("Bypass_field .......... %i\n", Bypass_field);
	mexPrintf("Coupling_field ........ %i\n", Coupling_field);
	mexPrintf("Max_Volts_field ....... %i\n", Max_Volts_field);
	mexPrintf("Max_EU_field .......... %i\n", Max_EU_field);
	mexPrintf("Time_His_field ........ %i\n", Time_His_field);
	*/
	/* ******************************************************************* */
	/* Populate the "C"-structure by calling the computational functions   */
	/* read_prn & read_vdf                                                 */
	/* ******************************************************************* */
	{
	    char *input_buf;
	    int   buflen, status;

			mxArray *Low_Pass_field_value;
			mxArray *Sample_Rate_field_value;
			mxArray *Num_Chan_field_value;
			mxArray *Time_Ref_field_value;

			mxArray *WD_field_value;

			int		bytes_to_copy;
			unsigned char *Ptr;


		/* ************************************************************ */
	    /*    Check for proper number of arguments                      */
		/* ************************************************************ */
	    if(nrhs!=1) 
	      mexErrMsgTxt("One input required.");
	    else if(nlhs > 1) 
	      mexErrMsgTxt("Too many output arguments.");

		/* ************************************************************ */
	    /*    Input must be a string                                    */
		/* ************************************************************ */
	    if ( mxIsChar(prhs[0]) != 1)
	      mexErrMsgTxt("Input must be a string.");

		/* ************************************************************ */
	    /*    Input must be a row vector                                */
		/* ************************************************************ */
	    if (mxGetM(prhs[0])!=1)
	      mexErrMsgTxt("Input must be a row vector.");
    
		/* ************************************************************ */
	    /*    Get the length of the input string                        */
		/* ************************************************************ */
	    buflen = (mxGetM(prhs[0]) * mxGetN(prhs[0])) + 1;

		/* ************************************************************ */
	    /*    Allocate memory for input string                          */
		/* ************************************************************ */
	    input_buf=mxCalloc(buflen, sizeof(char));

		/* ************************************************************ */
	    /* Copy the string data from prhs[0] into a C string input_buf. */
		/* ************************************************************ */
	    status = mxGetString(prhs[0], input_buf, buflen);
	    if(status != 0) 
	      mexWarnMsgTxt("Not enough space. String is truncated.");
    
		/* ************************************************************ */
	    /*    Call the C subroutines to build the Project structure     */
		/* ************************************************************ */
		read_vdf(input_buf, -1);
		read_prn(input_buf);

		/* sleep( (clock_t)(5 * CLOCKS_PER_SEC)); */

		/* ******************************************************************** */
		/*                  Populate the MATLAB structure                       */
		/* ******************************************************************** */
		for (index = 0; index < Project.Test_Item.Run.Num_Chan; index++)
		{
			mxArray *Time_His_field_value;
			mxArray *Max_EU_field_value;
			mxArray *Max_Volts_field_value;
			mxArray *Sensitivity_field_value;
			mxArray *ChanNbr_field_value;
			mxArray *Module_field_value;

			/* ******************************************************************** */
			/*                   Populate Chan structure:                           */
			/* ******************************************************************** */
			Module_field_value = mxCreateScalarDouble(Project.Test_Item.Run.Channel[index].Module);
			mxSetFieldByNumber(ChanStruct, index, Module_field, mxDuplicateArray(Module_field_value));

			ChanNbr_field_value = mxCreateScalarDouble(Project.Test_Item.Run.Channel[index].ChanNbr);
			mxSetFieldByNumber(ChanStruct, index, ChanNbr_field, mxDuplicateArray(ChanNbr_field_value));

			mxSetFieldByNumber(ChanStruct, index, Trans_Loc_field, mxCreateString(Project.Test_Item.Run.Channel[index].Trans_Loc));
			mxSetFieldByNumber(ChanStruct, index, Coordinate_field, mxCreateString(Project.Test_Item.Run.Channel[index].Coordinate));
			mxSetFieldByNumber(ChanStruct, index, Direction_field, mxCreateString(Project.Test_Item.Run.Channel[index].Direction));
			mxSetFieldByNumber(ChanStruct, index, Orientation_field, mxCreateString(Project.Test_Item.Run.Channel[index].Orientation));

			Sensitivity_field_value = mxCreateScalarDouble(Project.Test_Item.Run.Channel[index].Sensitivity);
			mxSetFieldByNumber(ChanStruct, index, Sensitivity_field, mxDuplicateArray(Sensitivity_field_value));

			mxSetFieldByNumber(ChanStruct, index, EU_field, mxCreateString(Project.Test_Item.Run.Channel[index].EU));
			mxSetFieldByNumber(ChanStruct, index, Trans_Type_field, mxCreateString(Project.Test_Item.Run.Channel[index].Trans_Type));
			mxSetFieldByNumber(ChanStruct, index, Cable_Ext_field, mxCreateString(Project.Test_Item.Run.Channel[index].Cable_Ext));
			mxSetFieldByNumber(ChanStruct, index, Serial_Num_field, mxCreateString(Project.Test_Item.Run.Channel[index].Serial_Num));
			mxSetFieldByNumber(ChanStruct, index, Bypass_field, mxCreateString(Project.Test_Item.Run.Channel[index].Bypass));
			mxSetFieldByNumber(ChanStruct, index, Coupling_field, mxCreateString(Project.Test_Item.Run.Channel[index].Coupling));

			Max_Volts_field_value = mxCreateScalarDouble(Project.Test_Item.Run.Channel[index].Max_Volts);
			mxSetFieldByNumber(ChanStruct, index, Max_Volts_field, mxDuplicateArray(Max_Volts_field_value));

			Max_EU_field_value = mxCreateScalarDouble(Project.Test_Item.Run.Channel[index].Max_EU);
			mxSetFieldByNumber(ChanStruct, index, Max_EU_field, mxDuplicateArray(Max_EU_field_value));

			/* ************************************************************************************************** */
		    /*  Call the C subroutine to extract the time history data and insert it into the Project structure   */
			/* ************************************************************************************************** */

			read_vdf(input_buf, index);

			Time_His_field_value = mxCreateNumericMatrix(1, HeaderRec1.Points, mxSINGLE_CLASS, mxREAL);
			Ptr = (unsigned char *) mxGetPr(Time_His_field_value);
			bytes_to_copy = HeaderRec1.Points * mxGetElementSize(Time_His_field_value);
			memmove(Ptr, Project.Test_Item.Run.Channel[index].Time_His, bytes_to_copy);
			mxSetFieldByNumber(ChanStruct, index, Time_His_field, mxDuplicateArray(Time_His_field_value));

			free(Project.Test_Item.Run.Channel[index].Time_His);

			mxDestroyArray(Time_His_field_value);
			mxDestroyArray(Max_EU_field_value);
			mxDestroyArray(Max_Volts_field_value);
			mxDestroyArray(Sensitivity_field_value);
			mxDestroyArray(ChanNbr_field_value);
			mxDestroyArray(Module_field_value);

		} /* end for (int index = 0; index < Num_Channels; index++) */

		/* ******************************************************************** */
		/*                     Populate Run structure:                          */
		/* ******************************************************************** */
		mxSetFieldByNumber(RunStruct, 0, Test_Date_field, mxCreateString(Project.Test_Item.Run.Test_Date));
		mxSetFieldByNumber(RunStruct, 0, Test_Type_field, mxCreateString(Project.Test_Item.Run.Test_Type));
		mxSetFieldByNumber(RunStruct, 0, Test_Level_field, mxCreateString(Project.Test_Item.Run.Test_Level));
		mxSetFieldByNumber(RunStruct, 0, Axis_field, mxCreateString(Project.Test_Item.Run.Axis));

		Time_Ref_field_value = mxCreateDoubleMatrix(1, HeaderRec1.Points, mxREAL);
		Ptr = (unsigned char *) mxGetPr(Time_Ref_field_value);
		bytes_to_copy = HeaderRec1.Points * mxGetElementSize(Time_Ref_field_value);
		memmove(Ptr, Project.Test_Item.Run.Time_Ref, bytes_to_copy);
		mxSetFieldByNumber(RunStruct, 0, Time_Ref_field, Time_Ref_field_value);

		free(Project.Test_Item.Run.Time_Ref);

		Num_Chan_field_value = mxCreateDoubleMatrix(1, 1, mxREAL);
		*mxGetPr(Num_Chan_field_value) = Project.Test_Item.Run.Num_Chan;
		mxSetFieldByNumber(RunStruct, 0, Num_Chan_field, Num_Chan_field_value);

		Sample_Rate_field_value = mxCreateDoubleMatrix(1, 1, mxREAL);
		*mxGetPr(Sample_Rate_field_value) = Project.Test_Item.Run.Sample_Rate;
		mxSetFieldByNumber(RunStruct, 0, Sample_Rate_field, Sample_Rate_field_value);

		Low_Pass_field_value = mxCreateDoubleMatrix(1, 1, mxREAL);
		*mxGetPr(Low_Pass_field_value) = Project.Test_Item.Run.Low_Pass;
		mxSetFieldByNumber(RunStruct, 0, Low_Pass_field, Low_Pass_field_value);
		mxSetFieldByNumber(RunStruct, 0, Setup_File_field, mxCreateString(Project.Test_Item.Run.Setup_File));
		mxSetFieldByNumber(RunStruct, 0, ADF_File_field,   mxCreateString(Project.Test_Item.Run.ADF_File));
		mxSetFieldByNumber(RunStruct, 0, Channel_field, ChanStruct);
		mxSetFieldByNumber(RunStruct, 0, Descrip_field, mxCreateString(Project.Test_Item.Run.Descrip));

		/* ******************************************************************** */
		/*                 Populate Test_Item structure:                        */
		/* ******************************************************************** */
		mxSetFieldByNumber(TestItemStruct, 0, TI_Name_field, mxCreateString(Project.Test_Item.Name));
		WD_field_value = mxCreateDoubleMatrix(1, 1, mxREAL);
		*mxGetPr(WD_field_value) = Project.Test_Item.WD;
		mxSetFieldByNumber(TestItemStruct, 0, WD_field, WD_field_value);
		mxSetFieldByNumber(TestItemStruct, 0, Run_field, RunStruct);

		/* ******************************************************************** */
		/*                      Populate Project structure:                     */
		/* ******************************************************************** */
		mxSetFieldByNumber(plhs[0], 0, Name_field, mxCreateString(Project.Name));
		mxSetFieldByNumber(plhs[0], 0, Test_Item_field, TestItemStruct);

	} /* End of code block to populate the "C"-structure */

		/* ******************************************************************** */
		/*                Free memory allocated by mxCreate routines            */
		/* ******************************************************************** */
/*
		mxDestroyArray(Num_Chan_field_value);
		mxDestroyArray(Low_Pass_field_value);
		mxDestroyArray(Module_field_value);
		mxDestroyArray(ChanNbr_field_value);
		mxDestroyArray(Sensitivity_field_value);
		mxDestroyArray(Max_Volts_field_value);
		mxDestroyArray(Max_EU_field_value);
*/
}

